/*
    作者：zx
    时间：2022.11.2
    描述：中断、异常相关参数和处理函数
*/

#ifndef IRQ_H
#define IRQ_H
#include "comm/types.h"

// devider zero 
#define IRQ0_DE 0

// debug 
#define IRQ1_DB 1

// Non Maskable Interrupt
#define IRQ2_NMI 2

// breakpoint 
#define IRQ3_BP 3

// overflow 
#define IRQ4_OF 4   

// BOUND range exceeded
#define IRQ5_BR 5

// invalid opcode (undefined opcode)
#define IRQ6_UD 6

// device not available (no math coprocessor)
#define IRQ7_NM 7

// double fault
#define IRQ8_DF 8

// coprocessor segment overrun(reserved)
#define IRQ9 9

// invalid tss
#define IRQ10_TS 10

// segment not present
#define IRQ11_NP 11

// stack segement fault
#define IRQ12_SS 12

// general protection
#define IRQ13_GP 13

// page fault
#define IRQ14_PF 14

// intel reserve. Do not used
#define IRQ15 15

// x87 FPU floating-point error(math error)
#define IRQ16_MF 16

// alignment check
#define IRQ17_AC 17

// machine check
#define IRQ18_MC 18

// SIMD floating-point exception
#define IRQ19_XM 19

// virtualization exception
#define IRQ20_VE 20

// control protection exception
#define IRQ21_CP 21

// IRQ22-IRQ31 intel reserve. Do not used

// 8259A中断序号从0x20开始

#define IRQ0X20_TIMER (0x20+0)  // 时间片中断的序号
#define IRQ0X21_KEYBOARD (0x20+1) // 键盘中断的序号
#define IRQ0X2E_HARDDISK_PRIMARY (0x20+14) // 键盘中断的序号

// 异常处理程序中 需要的数据结构体
typedef struct 
{
    uint32_t gs,fs,es,ds;
    uint32_t edi,esi,ebp,esp,ebx,edx,ecx,eax;
    uint32_t idx,error_code;
    uint32_t eip,cs,eflags;
    uint32_t esp3,ss3;
}exception_frame_t;

void irq_init(void);
void pic_init(void);
// 中断处理完成后 发送eoi命令
void irq_send_eoi(int irq_idx);
// 异常的处理程序声明
void exception_handler_unknown(void);
void exception_handler_divider(void);
void exception_handler_debug(void);
void exception_handler_NMI(void);
void exception_handler_breakpoint(void);
void exception_handler_overflow(void);
void exception_handler_bound_range(void);
void exception_handler_invalid_opcode(void);
void exception_handler_device_not_available(void);
void exception_handler_double_fault(void);

void exception_handler_invalid_tss(void);
void exception_handler_segement_not_present(void);
void exception_handler_stack_segment_fault(void);
void exception_handler_general_protection(void);
void exception_handler_page_fault(void);

void exception_handler_fpu_error(void);
void exception_handler_alignment_check(void);
void exception_handler_machine_check(void);
void exception_handler_simd_exception(void);
void exception_handler_virtual_exception(void);
void exception_handler_control_exception(void);


// 异常的实际处理
void do_handler_unknown(exception_frame_t *);
void do_handler_divider(exception_frame_t *);
void do_handler_debug(exception_frame_t *);
void do_handler_NMI(exception_frame_t *);
void do_handler_breakpoint(exception_frame_t *);
void do_handler_overflow(exception_frame_t *);
void do_handler_bound_range(exception_frame_t *);
void do_handler_invalid_opcode(exception_frame_t *);
void do_handler_device_not_available(exception_frame_t *);
void do_handler_double_fault(exception_frame_t *);

void do_handler_invalid_tss(exception_frame_t *);
void do_handler_segement_not_present(exception_frame_t *);
void do_handler_stack_segment_fault(exception_frame_t *);
void do_handler_general_protection(exception_frame_t *);
void do_handler_page_fault(exception_frame_t *);

void do_handler_fpu_error(exception_frame_t *);
void do_handler_alignment_check(exception_frame_t *);
void do_handler_machine_check(exception_frame_t *);
void do_handler_simd_exception(exception_frame_t *);
void do_handler_virtual_exception(exception_frame_t *);
void do_handler_control_exception(exception_frame_t *);

// 打印异常结构体信息
void exception_frame_info(exception_frame_t * exception_frame);

// 安装异常/中断处理程序入idt表 
int irq_install(int irq_num,uint32_t handler_addr);

// 中断处理程序初始化参数
// 第一块8259a芯片
#define PIC0_ICW1 0x20
#define PIC0_ICW2 0x21
#define PIC0_ICW3 0x21
#define PIC0_ICW4 0x21
// IMR控制引脚是否开启 1代表屏蔽 0代表开启
#define PIC0_IMR 0x21
#define PIC0_OCW2 0x20


// 第二块8259a芯片
#define PIC1_ICW1 0xA0
#define PIC1_ICW2 0xA1
#define PIC1_ICW3 0xA1
#define PIC1_ICW4 0xA1
#define PIC1_IMR 0xA1
#define PIC1_OCW2 0xA0

#define PIC_ICW1_ALWAYS_1 (1<<4)
#define PIC_ICW1_ICW4 (1 << 0)
// 8259A引脚从0x20开始
#define IRQ_PIC_START 0x20
#define PIC_ICW4_8086 (1 << 0)
#define PIC_OCW2_EOI (1<<5)

// 页面异常错误码 各位的意思
#define ERROR_PAGE_P    (1 << 0)  // 是否存在
#define ERROR_PAGE_RW   (1 << 1)  // 读写保护异常
#define ERROR_PAGE_US   (1 << 2)  // 用户/系统模式异常 

// 全局保护异常错误码 各位的意思
#define ERROR_EXT       (1 << 0)   
#define ERROR_IDT       (1 << 1)  // 描述符在idt/gdt中

void irq_disable(int irq_idx);
void irq_enable(int irq_idx);
void irq_disable_global(void);
void irq_enable_global(void);
void irq_init(void);

typedef uint32_t irq_status_t;
// 进入临界区,返回之前中断开关情况
irq_status_t irq_enter_protection(void);
// 退出临界区，将中断设置为进入临界区之前的情况
void irq_quit_protection(irq_status_t);

#endif // !IRQ_H